package protocol

import ext.toInt8

class BaseProtocol(val action: Int) {
    private val buffer = ByteArray(150)
    private var index = 0

    fun append7Byte(byte: Int): BaseProtocol {
        buffer[index++] = byte.toByte()
        return this
    }

    fun append7Int2(int2: Int): BaseProtocol {
        buffer[index++] = (int2 shr 7).toByte()
        buffer[index++] = (int2 and 0x7F).toByte()
        return this
    }

    fun append7Int4(int4: Int): BaseProtocol {
        buffer[index++] = (0x7F and (int4 shr 21)).toByte()
        buffer[index++] = (0x7F and (int4 shr 14)).toByte()
        buffer[index++] = (0x7F and (int4 shr 7)).toByte()
        buffer[index++] = (0x7F and int4).toByte()
        return this
    }

    fun appendAll(byteArray: ByteArray): BaseProtocol {
        System.arraycopy(byteArray, 0, buffer, index, byteArray.size)
        index += byteArray.size
        return this
    }

    fun appendByte(byte: Int): BaseProtocol {
        buffer[index++] = byte.toByte()
        return this
    }

    fun appendInt2(int2: Int): BaseProtocol {
        buffer[index++] = (int2 shr 8).toByte()
        buffer[index++] = int2.toByte()
        return this
    }

    fun appendInt4(int4: Int): BaseProtocol {
        buffer[index++] = (int4 shr 24).toByte()
        buffer[index++] = (int4 shr 16).toByte()
        buffer[index++] = (int4 shr 8).toByte()
        buffer[index++] = int4.toByte()
        return this
    }

    fun build(): ByteArray {
        val buf = ByteArray(index + 5)
        buf[0] = 0xE1.toByte()
        buf[1] = (index + 5).toByte()
        buf[2] = action.toByte()
        var c = 0
        for (i in 0 until index) {
            c = c xor (buffer[i].toInt8())
            buf[3 + i] = buffer[i]
        }
        buf[3 + index] = c.toByte()
        buf[4 + index] = 0xEF.toByte()

        return buf
    }

}